#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2020 crane <crane@crane-pc>
#
# Distributed under terms of the MIT license.

"""
    定义:
        side path: 不在环上的小路
        loop path: 整条环(28个数)
"""

class Solution:
    def __init__(self):
        # self.wired_num = 5      # 不走寻常路的有5个
        self.one_loop_num = 28  # 环上有28个
        self.init_map()

        self.assert_tests()     # 测试用例

    def init_map(self):
        self.real_to_easy_map = {}
        self.easy_to_real_map = {}
        self.make_real_easy_map( (31, 33) , -5)

        # self.weired_start = 19
        # self.weired_end   = 25

    def make_real_easy_map(self, real_range, change):
        self.real_to_easy_map[real_range] = change

        s, e = real_range
        self.easy_to_real_map[(s+change, e+change)] = -change

    def find_next_node(self, real_cur_pos, steps):
        if self.in_side(real_cur_pos):
            # print("go in side", real_cur_pos, steps)
            real_cur_pos, steps = self.go_side_path(real_cur_pos, steps)
            # print("2 go in side", real_cur_pos, steps)
        else:
            pass
            # print("not in side ", real_cur_pos, steps)

        if steps == 0:
            # side path把 steps都耗尽了
            return real_cur_pos

        if steps != 0:
            # side path没有耗尽steps, 或者压根没有进入side path
            easy_cur_pos = self.real_2_easy(real_cur_pos)
            return self.go_loop_path(easy_cur_pos, steps)

    # 判断是否从旁路开始(非环路)
    def go_side_path(self, real_cur_pos, steps):
        side_cur_pos = self.real_2_side(real_cur_pos)

        new_steps = 0
        print("in go _side", side_cur_pos, steps)
        if side_cur_pos + steps >= 31:
            new_steps = steps - (31 - side_cur_pos)
            new_side_cur_pos = 31
            # print('------------------- hit 1 ---------------------')
        elif side_cur_pos + steps <= 25:
            new_steps = steps + (side_cur_pos - 25)
            new_side_cur_pos = 25
            # print('------------------- hit 2---------------------')
        else:
            # print('------------------- hit 3---------------------')
            new_side_cur_pos = side_cur_pos + steps
            new_steps = 0

        return self.side_2_real(new_side_cur_pos), new_steps

    def real_2_easy(self, num):
        for range, change in self.real_to_easy_map.items():
            s, e = range
            if  s <= num <= e:
                num += change
                return num

        # 不变
        return num

    def easy_2_real(self, num):
        # print(self.easy_to_real_map)
        for range, change in self.easy_to_real_map.items():
            s, e = range
            if  s <= num <= e:
                num += change
                return num

        # 不变
        return num

    def in_side(self, num):
        if num in (19, 25):
            return True

        if 26 <= num <= 30:
            return True

        return False

    def real_2_side(self, num):
        assert num in (19, 25) or  26 <= num <= 30

        if num == 19:
            return 25
        if num == 25:
            return 31

        return num

    def side_2_real(self, num):
        if num == 31:
            return 25

        if num == 25:
            return 19

        return num

    def go_loop_path(self, easy_cur_pos, steps):
        rem = (easy_cur_pos + steps) % self.one_loop_num
        if rem == 0:
            result = self.one_loop_num
        else:
            result = rem

        return self.easy_2_real(result)

    def assert_tests(self):
        assert self.find_next_node(1, 4) == 5
        assert self.find_next_node(5, -4) == 1
        assert self.find_next_node(1, -1) == 33
        assert self.find_next_node(17, 5) == 22
        assert self.find_next_node(17, 5) == 22
        assert self.find_next_node(19, 2) == 27
        assert self.find_next_node(30, 3) == 32
        assert self.find_next_node(33, 3) == 3

        assert self.find_next_node(32, -4) == 23
        assert self.find_next_node(27, -3) == 18
        assert self.find_next_node(28, -4) == 18
        assert self.find_next_node(28, -3) == 19

        assert self.find_next_node(1, -2) == 32

def test():
    s = Solution()

def main():
    print("start main")
    test()

if __name__ == "__main__":
    main()
